iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0

day23_title

前言

我們做網頁或做服務來說,最無法避免的就肯定是部署的部分,
當然現在這年頭, docker 與 git 差不多,基本上為現代工程師的標配了
所以我們今天要把 bun 建置的服務容器化後上到 docker
雖然 bun 在操作上與 nodejs 很像,但我還是要說當年我還在 bun beta 版時
我被吸引的是打包效率與 nodejs 本身不是同一個檔次,
不過當時, bun 上 docker 確實踩到一些雷,不過現在 bun 非常穩定了,在 docker
打包時整個要快又穩

開啟一個新專案

今天的主題主要在講部署,所以我們把焦點放在部署本身,我們的 endpoint
就盡可能簡單,通常我們在開發時,起手式通常是把 infra 先搞定,然後服務的部分先簡單
至少前後端到部署一條龍先做掉,之後每次部署的成功於否都用 CI/CD 搞定

後端

所以我們先搞個 hello world 的簡單服務出來,扣就長得以下這樣就好

index.ts

console.log('你跑在 http://localhost:3000');

Bun.serve({
  port: 3000,
  routes: {
    '/': {
      GET: (): Response => {
        return Response.json({
          message: '開心部署!開心就好'
        }, { status: 200 })
      }
    }
  }
})

重點是 Dockerfile 我們這裡先寫一個簡單的版本

FROM oven/bun:latest

WORKDIR /app

COPY package.json bun.lock ./

RUN bun install --frozen-lockfile

COPY . . 

RUN bun build . --outdir dist

ENTRYPOINT ["bun", "run", "dist/index.js"]

打包 try try 看

docker build -t testa . 

補充 : 這個 testa 是我隨便命名的 image 名稱

看一下 size :

disk usage content size
372MB 96.2MB

image size

跑起來看看

docker run -d -p 3000:3000 testa

result_1

優化 Dockerfile

雖然簡單寫個 Dockerfile 但我們對打包的體積不太滿意,所以考慮用 Multi-stage 去優化

FROM oven/bun:latest AS builder

WORKDIR /app

COPY package.json bun.lock ./

RUN bun install --frozen-lockfile

COPY . . 

RUN bun build . --outdir dist --target bun

FROM oven/bun:slim

WORKDIR /app

COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json

USER bun

EXPOSE 3000

ENTRYPOINT ["bun", "run", "dist/index.js"]

打包結果2

看一下 size :

disk usage content size
269MB 67.5MB

顯然各方面都小了一些

前端

我們這裡也簡單啟動一個前端的專案
關於啟動方式可以參考前一篇 day22 的部分

一樣我們著重點在於 Dockerfile

FROM oven/bun:latest as build
WORKDIR /app
COPY package*.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . . 
RUN bun run build

FROM nginx:stable-alpine as prod-stage
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d/
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

nginx conf

default.conf

server {
  listen 80;
  server_name _ default_server;

  root /usr/share/nginx/html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}

我們打包看看

docker build -t testa . 
docker run -d -p 5173:80 testa
# 我們 host 在 5173

前端映像

整理

今天我們把 Bun 應用從開發到容器化部署走了一遍完整流程,重點整理如下:

後端部分

  • 用 Bun.serve 快速建出一個最小可運行的服務作為部署驗證的基礎
  • 從單階段 Dockerfile 出發,先求能跑起來
  • 導入 Multi-stage build 後,image 體積明顯下降(disk usage 從 372MB 降到 269MB,content size 從 96.2MB 降到 67.5MB),也更符合正式環境「只帶執行所需檔案」的原則
  • 搭配 oven/bun:slim 作為最終執行環境、以非 root 的 USER bun 執行,兼顧了體積與安全性

前端部分

  • 同樣採用 Multi-stage:第一階段用 Bun 建置靜態檔案,第二階段丟進 nginx:stable-alpine 提供服務
  • 自訂 default.conf 處理 SPA 常見的路由 fallback(try_files ... /index.html),避免重新整理時出現 404

結論

我們先把 Dockerfile 這回我們已經把 CI/CD 的地基與前後端的部分整理好了,
未來整合 CI/CD 以及部署到其他地方已經準備好了!讓我們往下一篇走


上一篇
前端整合:Bun + React + Vite 的開發工作流以及前端測試
下一篇
Bun 在 CI/CD 的應用:GitHub Actions 加速你的 Pipeline(上篇)
系列文
不只是快 —— Bun 30 天:從底層架構、全套工具鏈到生產部署24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言